package com.hmdp.utils.redis.impl;

import cn.hutool.core.lang.UUID;
import com.hmdp.utils.redis.ILock;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

import static com.hmdp.utils.RedisConstants.LOCK_KEY_PRE;

/**
 * ClassName:SimpleRedisLock
 */
public class SimpleRedisLock implements ILock {

    // 锁的key
    private String lockKey;
    private StringRedisTemplate stringRedisTemplate;

    public SimpleRedisLock(String lockKey, StringRedisTemplate stringRedisTemplate){
        this.lockKey = lockKey;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    // UUID默认会带有横线，参数isSimple表示是否把横线去除，true为去除
    private static final String ID_PRE = UUID.randomUUID().toString(true) + "-";

    // 设置Lua脚本的...
    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
    static{
        // 初始化
        UNLOCK_SCRIPT = new DefaultRedisScript<>();
        // 加载lua文件资源
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("script\\unlock.lua"));
        // 设置返回值类型
        UNLOCK_SCRIPT.setResultType(Long.class);
    }

    @Override
    public boolean tryLock(long timeoutSec) {
        // 获取线程标示
        String threadId =ID_PRE + Thread.currentThread().getId();
        // 尝试获取锁, value表示那个线程获取了锁
        Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY_PRE + lockKey, threadId, timeoutSec, TimeUnit.SECONDS);
        // 为防止Unboxing of 'flag' may produce 'NullPointerException' ，也就是flag有可能是null，然后return flag自动拆箱时就会报错
        return Boolean.TRUE.equals(flag);
    }

    /*
    @Override
    public void unLock() {
        //获取当前线程标识
        String threadIdCur = ID_PRE + Thread.currentThread().getId();
        //获取当前锁的线程标识
        String threadId = stringRedisTemplate.opsForValue().get(LOCK_KEY_PRE + lockKey);
        //如果标识一致则释放锁
        if(threadIdCur.equals(threadId)){
            //释放锁
            stringRedisTemplate.delete(LOCK_KEY_PRE + lockKey);
        }
    }
    */


    /**
     * 使用RedisTemplate调用Lua脚本的API接口
     */
    @Override
    public void unLock() {
        //调用lua
        stringRedisTemplate.execute(
                UNLOCK_SCRIPT,// Lua脚本文件的加载
                Collections.singletonList(LOCK_KEY_PRE + lockKey),// 快捷创建单个元素的集合List
                ID_PRE + Thread.currentThread().getId() // ThreadId
        );
    }
}
